/*
 *
 * Copyright (c) 2020 The Raptor Authors. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#ifndef RAPTOR_LITE_UTILS_LOG_H_
#define RAPTOR_LITE_UTILS_LOG_H_

#include <stdlib.h>
#include <string.h>
#include "raptor-lite/utils/useful.h"

namespace raptor {
enum class LogLevel : int { kDebug, kInfo, kWarn, kError, kFatal };

typedef struct {
    const char *message;
    int line;
    LogLevel level;
    unsigned long threadid;
} LogArgument;

typedef void (*LogPrintCallback)(LogArgument *arg);

const char *LogLevelToString(LogLevel level);
LogLevel LogLevelByString(const char *str);
void LogEnableColor(bool enable);
void LogSetLevel(LogLevel level);
void LogFormatPrint(int line, LogLevel level, const char *format, ...);
void LogSetPrintCallback(LogPrintCallback callback);
} // namespace raptor

#define log_debug(FMT, ...)                                                                        \
    do {                                                                                           \
        ::raptor::LogFormatPrint(__LINE__, ::raptor::LogLevel::kDebug, FMT, ##__VA_ARGS__);        \
    } while (0)

#define log_info(FMT, ...)                                                                         \
    do {                                                                                           \
        ::raptor::LogFormatPrint(__LINE__, ::raptor::LogLevel::kInfo, FMT, ##__VA_ARGS__);         \
    } while (0)

#define log_warn(FMT, ...)                                                                         \
    do {                                                                                           \
        ::raptor::LogFormatPrint(__LINE__, ::raptor::LogLevel::kWarn, FMT, ##__VA_ARGS__);         \
    } while (0)

#define log_error(FMT, ...)                                                                        \
    do {                                                                                           \
        ::raptor::LogFormatPrint(__LINE__, ::raptor::LogLevel::kError, FMT, ##__VA_ARGS__);        \
    } while (0)

#define log_fatal(FMT, ...)                                                                        \
    do {                                                                                           \
        ::raptor::LogFormatPrint(__LINE__, ::raptor::LogLevel::kFatal, FMT, ##__VA_ARGS__);        \
    } while (0)

#define RAPTOR_ASSERT(x)                                                                           \
    do {                                                                                           \
        if (RAPTOR_UNLIKELY(!(x))) {                                                               \
            raptor::LogFormatPrint(__LINE__, ::raptor::LogLevel::kFatal, "assertion failed: %s",   \
                                   #x);                                                            \
            abort();                                                                               \
        }                                                                                          \
    } while (0)

#endif // RAPTOR_LITE_UTILS_LOG_H_
